{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Message模块\n",
    "\n",
    "## 简介\n",
    "\n",
    "`Message`是对大语言模型输入输出信息的封装，可以简化大家和大语言模型的交互。\n",
    "\n",
    "在`ERNIE Bot Agent`中，主要有如下4类`Message`：\n",
    "\n",
    "* `HumanMessage`：用户输入给模型的普通信息，比如聊天的问题。\n",
    "* `SystemMessage`：用户输入给模型的全局信息，比如角色扮演的指令、输出格式设置的指令。\n",
    "* `AIMessage`：模型返回的信息，比如聊天的回答、触发`Function call`的回答。\n",
    "* `FunctionMessage`：上一轮模型的输出是带有`Funciton call`的`AIMessage`，则用户需要首先调用`Function`，然后将`Function`的结果输入给大语言模型。\n",
    "\n",
    "`Message`模块的详细API接口，请参考[文档](https://ernie-bot-agent.readthedocs.io/zh-cn/latest/package/erniebot_agent/message/)。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 上手使用Message\n",
    "\n",
    "### 安装\n",
    "\n",
    "大家可以参考[官方文档](https://github.com/PaddlePaddle/ERNIE-SDK)，进行安装ERNIE Bot。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 鉴权\n",
    "\n",
    "大家在使用ERNIE Bot Agent之前，需要完成鉴权步骤：\n",
    "\n",
    "* 在[AI Studio星河社区](https://aistudio.baidu.com/index)注册并登录账号\n",
    "* 在个人中心的[访问令牌页面](https://aistudio.baidu.com/index/accessToken)获取用户凭证`Access Token`\n",
    "* 通过环境变量或者`Python`代码设置`Access Token`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-12-28T13:06:12.326963Z",
     "iopub.status.busy": "2023-12-28T13:06:12.326405Z",
     "iopub.status.idle": "2023-12-28T13:06:12.331628Z",
     "shell.execute_reply": "2023-12-28T13:06:12.330770Z",
     "shell.execute_reply.started": "2023-12-28T13:06:12.326921Z"
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "# %env EB_AGENT_ACCESS_TOKEN=xxxxxxxx\n",
    "\n",
    "import os\n",
    "\n",
    "os.environ[\"EB_AGENT_ACCESS_TOKEN\"] = \"xxxxxxxx\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用Message\n",
    "\n",
    "首先，导入必要的依赖库。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-12-28T13:06:15.871481Z",
     "iopub.status.busy": "2023-12-28T13:06:15.870805Z",
     "iopub.status.idle": "2023-12-28T13:06:15.875761Z",
     "shell.execute_reply": "2023-12-28T13:06:15.874921Z",
     "shell.execute_reply.started": "2023-12-28T13:06:15.871448Z"
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import json\n",
    "import asyncio\n",
    "import erniebot\n",
    "from erniebot_agent.chat_models import ERNIEBot\n",
    "from erniebot_agent.memory import HumanMessage, AIMessage, SystemMessage, FunctionMessage"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "大家在使用`ERNIE Bot`调用文心一言进行多轮对话时，需要按照规范定义每轮对话的信息（如下），稍显复杂。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "erniebot.api_type = \"aistudio\"\n",
    "erniebot.access_token = \"<access-token-for-aistudio>\"\n",
    "messages = [\n",
    "    {\"role\": \"user\", \"content\": \"我在深圳，周末可以去哪里玩\"},\n",
    "    {\"role\": \"assistant\", \"content\": \"深圳有许多著名的景点，以下是三个推荐景点：1. 深圳世界之窗，2. 深圳欢乐谷，3. 深圳东部华侨城。\"},\n",
    "    {\"role\": \"user\", \"content\": \"从你推荐的三个景点中，选出最值得去的景点是什么，直接给出景点名字即可\"},\n",
    "]\n",
    "response = erniebot.ChatCompletion.create(model=\"ernie-3.5\", messages=messages)\n",
    "\n",
    "print(response.get_result())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果基于`ERNIE Bot Agent`调用文心一言，大家使用`Message`模块，可以较好地简化代码。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-12-28T13:06:20.347461Z",
     "iopub.status.busy": "2023-12-28T13:06:20.346882Z",
     "iopub.status.idle": "2023-12-28T13:06:21.341124Z",
     "shell.execute_reply": "2023-12-28T13:06:21.339980Z",
     "shell.execute_reply.started": "2023-12-28T13:06:20.347428Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最值得去的景点是深圳欢乐谷。\r\n"
     ]
    }
   ],
   "source": [
    "model = ERNIEBot(model=\"ernie-3.5\")\n",
    "# 使用Message模块\n",
    "messages = [\n",
    "    HumanMessage(\"我在深圳，周末可以去哪里玩\"),\n",
    "    AIMessage(\"深圳有许多著名的景点，以下是三个推荐景点：1. 深圳世界之窗，2. 深圳欢乐谷，3. 深圳东部华侨城。\"),\n",
    "    HumanMessage(\"从你推荐的三个景点中，选出最值得去的景点是什么，直接给出景点名字即可\"),\n",
    "]\n",
    "ai_message = await model.chat(messages=messages)\n",
    "print(ai_message.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "创建各种`Message`的示例代码如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-12-28T13:06:24.715551Z",
     "iopub.status.busy": "2023-12-28T13:06:24.714968Z",
     "iopub.status.idle": "2023-12-28T13:06:24.721387Z",
     "shell.execute_reply": "2023-12-28T13:06:24.720566Z",
     "shell.execute_reply.started": "2023-12-28T13:06:24.715521Z"
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<role: 'user', content: '你好，你是谁？'>\r\n",
      "<role: 'system', content: '你是一名数学老师，使用浅显易懂的方法来回答问题', token_count: 23>\r\n",
      "<role: 'function', name: 'get_current_temperature', content: '{\"temperature\": 25, \"unit\": \"摄氏度\"}'>\r\n"
     ]
    }
   ],
   "source": [
    "human_message = HumanMessage(content=\"你好，你是谁？\")\n",
    "\n",
    "system_message = SystemMessage(content=\"你是一名数学老师，使用浅显易懂的方法来回答问题\")\n",
    "\n",
    "result = {\"temperature\": 25, \"unit\": \"摄氏度\"}\n",
    "function_message = FunctionMessage(\n",
    "    name=\"get_current_temperature\", content=json.dumps(result, ensure_ascii=False)\n",
    ")\n",
    "\n",
    "print(human_message)\n",
    "print(system_message)\n",
    "print(function_message)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用`SystemMessage`的示例代码如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-12-28T13:06:27.349838Z",
     "iopub.status.busy": "2023-12-28T13:06:27.348519Z",
     "iopub.status.idle": "2023-12-28T13:06:40.051156Z",
     "shell.execute_reply": "2023-12-28T13:06:40.050364Z",
     "shell.execute_reply.started": "2023-12-28T13:06:27.349786Z"
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "勾股定理是一个基本的几何定理，它指出在一个直角三角形中，直角边的平方和等于斜边的平方。换句话说，如果我们知道一个直角三角形的两个直角边的长度，我们就可以使用勾股定理来找出斜边的长度。这个定理在中国古代被称为“勾股定理”，因为在古代，人们把较短的直角边称为“勾”，较长的直角边称为“股”，而斜边则被称为“弦”。这个定理也可以被写作 a² + b² = c² 的形式，其中 a 和 b 是直角三角形的两个直角边，c 是斜边。\r\n",
      "\r\n",
      "勾股定理是人类早期发现并证明的重要数学定理之一，它可以用代数思想解决几何问题，也是数形结合的纽带之一。这个定理有很多种证明方法，据统计，目前已知的证明方法约有500种，是数学定理中证明方法最多的定理之一。在中国，周朝时期的商高提出了“勾三股四弦五”的勾股定理的特例。在西方，最早提出并证明此定理的为公元前6世纪古希腊的毕达哥拉斯学派。\r\n",
      "\r\n",
      "这个定理在数学、物理、工程等多个领域都有应用，并且也有很多重要的实际应用，例如计算直角三角形的角度、求解几何问题、设计建筑结构等等。因此，理解和掌握勾股定理是非常重要的。\r\n"
     ]
    }
   ],
   "source": [
    "model = ERNIEBot(model=\"ernie-3.5\")\n",
    "system_message = SystemMessage(content=\"你是一名数学老师，尽量使用浅显易懂的方法来解答问题\")\n",
    "messages = [HumanMessage(\"勾股定理是什么\")]\n",
    "ai_message = await model.chat(messages=messages, system=system_message.content)\n",
    "print(ai_message.content)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "py35-paddle1.2.0"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
